home *** CD-ROM | disk | FTP | other *** search
/ Best of Shareware / Best of PC Windows Shareware 1.0 - Wayzata Technology (7111) (1993).iso / mac / ZIPPED / DOS / GRAPHICS / POVSRC.ZIP / MACHINE.ZIP / UNIX.ZIP / XWINDOWS.C < prev    next >
C/C++ Source or Header  |  1992-03-18  |  17KB  |  619 lines

  1. /****************************************************************************
  2. *                xwindows.c
  3. *
  4. *  This module implements X-windows specific routines.
  5. *
  6. *  from Persistence of Vision Raytracer 
  7. *  Copyright 1991 Persistence of Vision Team
  8. *---------------------------------------------------------------------------
  9. *  Copying, distribution and legal info is in the file povlegal.doc which
  10. *  should be distributed with this file. If povlegal.doc is not available
  11. *  or for more info please contact:
  12. *
  13. *       Drew Wells [POV-Team Leader] 
  14. *       CIS: 73767,1244  Internet: 73767.1244@compuserve.com
  15. *       Phone: (213) 254-4041
  16. * This program is based on the popular DKB raytracer version 2.12.
  17. * DKBTrace was originally written by David K. Buck.
  18. * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  19. *
  20. *****************************************************************************/
  21.  
  22.  /*
  23.  * Here are some routines I wrote which implement +d option on unix computers
  24.  * running X-windows. For now, only black and white output is supported. If I
  25.  * get access to a computer with a color monitor, I'll probably add support
  26.  * for colors to my routines.
  27.  * 
  28.  * In future I'll probably add some more dithering methods. I have tested these
  29.  * routines on SUN 3 and SUN 4. I'm using the tvtwm window manager.
  30.  * 
  31.  * If you have some suggestions to my source code or if you change anything,
  32.  * please let me know. I can be reached at the following address: Marek
  33.  * Rzewuski, Avstikkeren 11, 1156 Oslo 11, Norway or marekr@ifi.uio.no on
  34.  * Internet.
  35.  */
  36.  
  37. /*
  38.  * 91-07-29 Allan H. Wax (Wax.OSBU_South@Xerox.COM) Hacked this module so it
  39.  * can be used with either a colour or B&W screen. Made all variables local
  40.  * to this routine (no need for more globals if no one ever uses them). Fixed
  41.  * bug in refresh routine. Use dither from colorx.c. Use xpov.icon instead of
  42.  * theIcon.
  43.  */
  44.  
  45. #include <stdio.h>
  46. #include <X11/Xlib.h>        /* some Xlib stuff */
  47. #include <X11/Xutil.h>
  48. #include <X11/Xos.h>
  49. #include <X11/Xatom.h>
  50. #include "xpov.icn"
  51. #include <math.h>
  52.  
  53. #include "frame.h"
  54. #include "povproto.h"
  55.  
  56. #define     BORDER_WIDTH    2
  57. #define    EV_MASK    (ButtonPressMask | \
  58.          KeyPressMask     | \
  59.          ExposureMask    | \
  60.          StructureNotifyMask)
  61.  
  62. static Display *theDisplay;
  63. static int      theScreen;
  64. static int      theDepth;
  65. static unsigned long theBlackPixel;
  66. static unsigned long theWhitePixel;
  67. static XEvent   theEvent;
  68. static Window   theWindow, openWindow();
  69. static GC       theGC;
  70. static unsigned char *bitmap;    /* pointer to our picture bitmap */
  71. static unsigned char *bitmapPos;/* position to the last drawn pixel in our
  72.                  * bitmap */
  73.  
  74.  
  75. static char    *display_name = 0;
  76. static int     disp_wide, disp_high;
  77. static XImage  *xi;
  78. static char    *data;
  79. static XGCValues gcvalues;
  80. static long     colorpixels[256];
  81. static Bool     iscolor;
  82. static int     screen_open = 0;
  83.  
  84. struct {
  85.     void            (*Init) ();
  86.     void            (*Close) ();
  87.     void            (*Finished) ();
  88.     void            (*Plot) ();
  89. }               display;
  90.  
  91. /* global POVRay variables */
  92.  
  93. extern FRAME    Frame;
  94. extern unsigned int Options;
  95. extern char     DisplayFormat;
  96. extern int      First_Line;
  97.  
  98. /*
  99.  * Sets up a connection to the X server and stores informations about the
  100.  * enviroment
  101.  */
  102.  
  103. static          initX()
  104. {
  105.     theDisplay = XOpenDisplay(NULL);
  106.     if (theDisplay == NULL) {
  107.     fprintf(stderr, "ERROR: Cannot establish a connection to the X server %s\n",
  108.         XDisplayName(NULL));
  109.     exit(1);
  110.     }
  111.     theScreen = DefaultScreen(theDisplay);
  112.     theDepth = DefaultDepth(theDisplay, theScreen);
  113.     theWhitePixel = WhitePixel(theDisplay, theScreen);
  114.     theBlackPixel = BlackPixel(theDisplay, theScreen);
  115. }
  116.  
  117. /*
  118.  * This procedure will do the following things: 1)     Set up attributes
  119.  * desired for the window 2)    Set up an icon to our window. 3)     Send
  120.  * hints to the window manager. 4)     Open a window on the display 5)    Tell
  121.  * the X to place the window on the screen 6)    Flush out all the queued up X
  122.  * requests to the X server
  123.  */
  124.  
  125. static Window   openWindow(x, y, width, height, flag, theNewGC)
  126. int             x, y;
  127. int             width, height;
  128. int             flag;
  129. GC             *theNewGC;
  130. {
  131.     XSetWindowAttributes theWindowAttributes;
  132.     XSizeHints      theSizeHints;
  133.     unsigned long   theWindowMask;
  134.     Window          theNewWindow;
  135.     Pixmap          theIconPixmap;
  136.     XWMHints        theWMHints;
  137.  
  138.  
  139.     /*
  140.      * Set up some attributes for the window. Override_redirect tells the
  141.      * window manager to deal width the window or leave it alone
  142.      */
  143.  
  144.     theWindowAttributes.border_pixel = theBlackPixel;
  145.     theWindowAttributes.background_pixel = theWhitePixel;
  146.     theWindowAttributes.override_redirect = False;
  147.     theWindowMask = CWBackPixel | CWBorderPixel | CWOverrideRedirect;
  148.  
  149.     /* Now, open out window */
  150.  
  151.     theNewWindow = XCreateWindow(theDisplay,
  152.                  RootWindow(theDisplay, theScreen),
  153.                  x, y,
  154.                  width, height,
  155.                  BORDER_WIDTH,
  156.                  theDepth,
  157.                  InputOutput,
  158.                  CopyFromParent,
  159.                  theWindowMask,
  160.                  &theWindowAttributes);
  161.  
  162.     /* Create one iconbitmap */
  163.  
  164.     theIconPixmap = XCreateBitmapFromData(theDisplay,
  165.                       theNewWindow,
  166.                       xpov_bits,
  167.                       xpov_width,
  168.                       xpov_height);
  169.  
  170.     /*
  171.      * Now tell the window manager where on screen we should place our
  172.      * window.
  173.      */
  174.  
  175.     theWMHints.icon_pixmap = theIconPixmap;
  176.     theWMHints.initial_state = NormalState;    /* we don't want an iconized
  177.                          * window when it's created */
  178.     theWMHints.flags = IconPixmapHint | StateHint;
  179.  
  180.     XSetWMHints(theDisplay, theNewWindow, &theWMHints);
  181.  
  182.     theSizeHints.flags = PPosition | PSize;
  183.     theSizeHints.x = x;
  184.     theSizeHints.y = y;
  185.     theSizeHints.width = width;
  186.     theSizeHints.height = height;
  187.     /*
  188.      * theSizeHints.min_width    = width; theSizeHints.min_height    =
  189.      * height; theSizeHints.max_width    = width; theSizeHints.max_height =
  190.      * height;
  191.      */
  192.  
  193.     XSetNormalHints(theDisplay, theNewWindow, &theSizeHints);
  194.  
  195.  
  196.     if (createGC(theNewWindow, theNewGC) == 0) {
  197.     XDestroyWindow(theDisplay, theNewWindow);
  198.     return ((Window) 0);
  199.     }
  200.  
  201.     /* make a name for our window */
  202.  
  203.     XStoreName(theDisplay, theNewWindow, "POVRay \0");
  204.  
  205.     /*
  206.      * Now, could we please see the window on the screen? Until now, we have
  207.      * dealed with a window which has been created but noe appeared on the
  208.      * screen. Maping the window places it visibly    on the screen
  209.      */
  210.  
  211.     XMapWindow(theDisplay, theNewWindow);
  212.     XFlush(theDisplay);
  213.     return (theNewWindow);
  214. }
  215.  
  216. static          refreshWindow(theExposedWindow)
  217. Window          theExposedWindow;
  218. {
  219.     int             i = 0, x = 0, y = First_Line;
  220.     register unsigned char *dummy = bitmap;
  221.     while (dummy != bitmapPos) {
  222.     /* draw until most current pixel is drawn */
  223.     if (*dummy)
  224.         XDrawPoint(theDisplay, theWindow, theGC, x, y);
  225.     if (x == Frame.Screen_Width) {
  226.         x = 0;
  227.         y++;
  228.     }
  229.     else {
  230.         dummy++;
  231.         x++;
  232.         i++;
  233.     }
  234.     }
  235.     XFlush(theDisplay);
  236. }
  237.  
  238. /* Creates a new graphics context */
  239.  
  240. static int      createGC(theNewWindow, theNewGC)
  241. Window          theNewWindow;
  242. GC             *theNewGC;
  243. {
  244.     XGCValues       theGCValues;
  245.     *theNewGC = XCreateGC(theDisplay,
  246.               theNewWindow,
  247.               (unsigned long) 0,
  248.               &theGCValues);
  249.  
  250.     if (*theNewGC == 0) {
  251.     return (0);        /* error */
  252.     }
  253.     else {            /* set foreground and background defaults for
  254.                  * the new GC */
  255.     XSetForeground(theDisplay,
  256.                *theNewGC,
  257.                theBlackPixel);
  258.  
  259.     XSetBackground(theDisplay,
  260.                *theNewGC,
  261.                theWhitePixel);
  262.  
  263.     return (1);        /* OK */
  264.     }
  265. }
  266.  
  267. static          initEvents(theWindow)
  268. Window          theWindow;
  269. {
  270.     XSelectInput(theDisplay,
  271.          theWindow,
  272.          EV_MASK);
  273. }
  274.  
  275. void            BWFinished()
  276. {
  277.  
  278. }
  279.  
  280.  
  281. void            BWInit()
  282. {
  283.     int             i;
  284.  
  285.     /*
  286.      * set some room for a bitmap for our picture. I've got to "remember" the
  287.      * whole picture bacuse of resizing of the window, overlapping etc. Then
  288.      * I've got to refresh the picture. This should be easy to convert to an
  289.      * "color version" in future
  290.      */
  291.  
  292.     bitmap = (unsigned char *) malloc(sizeof(unsigned char) *
  293.                 (Frame.Screen_Width * Frame.Screen_Height));
  294.     bitmapPos = bitmap;
  295.     if (bitmap == NULL)
  296.     printf("ERROR: Can not allocate the buffer..\n");
  297.  
  298.     for (i = 0; i < (Frame.Screen_Width * Frame.Screen_Height); i++) {
  299.     *bitmapPos++ = 0;
  300.     }
  301.     bitmapPos = bitmap;
  302.     initX();
  303.     theWindow = openWindow(0, 0, Frame.Screen_Width, Frame.Screen_Height, 0, &theGC);
  304.     initEvents(theWindow);
  305.     XFlush(theDisplay);
  306.     XNextEvent(theDisplay, &theEvent);
  307.     XFlush(theDisplay);
  308. }                /* end of display initilazation */
  309.  
  310. void            BWClose()
  311. {
  312.     sleep(10);            /* an simple delay. 10 seconds. */
  313.     XDestroyWindow(theDisplay, theWindow);
  314.     XFlush(theDisplay);
  315.     XCloseDisplay(theDisplay);
  316.     free(bitmap);
  317. }
  318.  
  319. void            BWPlot(x, y, Red, Green, Blue)
  320. int             x, y;
  321. unsigned char   Red, Green, Blue;
  322. {
  323.     unsigned char   color;
  324.     long            thePixel;
  325.     /* lets find if there are some events waiting for us */
  326.  
  327.     while (XPending(theDisplay) > 0) {    /* now deal with the events.. */
  328.     XNextEvent(theDisplay, &theEvent);
  329.  
  330.     switch (theEvent.type) {
  331.       case Expose:
  332.         /* printf("Window is exposed.\n"); */
  333.         refreshWindow(theEvent.xany.window);
  334.         break;
  335.  
  336.       case MapNotify:
  337.         /* printf("The window is mapped.\n"); */
  338.         refreshWindow(theEvent.xany.window);
  339.         break;
  340.  
  341.       case ButtonPress:
  342.         /* printf("A mouse button was pressed.\n"); */
  343.         break;
  344.  
  345.       case ConfigureNotify:
  346.         /* printf("The window configuration has been changed\n"); */
  347.         refreshWindow(theEvent.xany.window);
  348.         break;
  349.     }
  350.     }
  351.     if (dither(x, y, Red, Green, Blue)) {
  352.     thePixel = BlackPixel(theDisplay, theScreen);
  353.     XDrawPoint(theDisplay, theWindow, theGC, x, y);
  354.     XFlush(theDisplay);
  355.     }
  356.     else {
  357.     thePixel = WhitePixel(theDisplay, theScreen);
  358.     }
  359.     *bitmapPos++ = thePixel;
  360. }
  361.  
  362. /* so we can get at the dimensions */
  363. extern FRAME    Frame;
  364.  
  365. /* x11 stuff */
  366.  
  367. static Bool     evtPred(d, e, a)
  368. Display        *d;
  369. XEvent         *e;
  370. char           *a;
  371. {
  372.     return (True);
  373. }
  374.  
  375. static void     BuildColormap()
  376. {
  377.     XColor          tmp;
  378.     register unsigned short r, g, b, i;
  379.     Colormap        cmap;
  380.  
  381.     /*
  382.      * build a colormap that will contain 216, or 6^3 colors. We won't do
  383.      * anything clever like adding extra grays in the leftover space.
  384.      * Remember, this was written in a few hours.
  385.      */
  386.     cmap = DefaultColormap(theDisplay, theScreen);
  387.  
  388.     i = 0;
  389.     for (r = 0; r < 6; r++) {
  390.     for (g = 0; g < 6; g++) {
  391.         for (b = 0; b < 6; b++, i++) {
  392.         tmp.red = (r * 36) << 8;
  393.         tmp.green = (g * 36) << 8;
  394.         tmp.blue = (b * 36) << 8;
  395.         tmp.flags = DoRed | DoGreen | DoBlue;
  396.         if (!XAllocColor(theDisplay, cmap, &tmp))
  397.             goto crap_out;
  398.         colorpixels[i] = tmp.pixel;
  399.         }
  400.     }
  401.     }
  402. crap_out:            /* couldn't get what we wanted.  Boo-hoo. */
  403.     if (i != 216)
  404.     fprintf(stderr, "warning: could only get %d colors.\n", i);
  405. }
  406.  
  407. void            ColourFinished()
  408. {
  409.     XEvent         *report;
  410.     /* do nothing.  I suppose we could wait... */
  411.     while (1) {
  412.     XNextEvent(theDisplay, &report);
  413.     XPutImage(theDisplay, theWindow, theGC, xi, 0, 0, 0, 0, Frame.Screen_Width,
  414.           Frame.Screen_Height);
  415.     }
  416. }
  417.  
  418. void            display_close()
  419. {
  420.     if(screen_open)
  421.             (display.Close) ();
  422. }
  423.  
  424. void            display_plot(x, y, Red, Green, Blue)
  425. int             x, y;
  426. unsigned char   Red, Green, Blue;
  427. {
  428.     (display.Plot) (x, y, Red, Green, Blue);
  429. }
  430.  
  431. void            display_finished()
  432. {
  433.     if(screen_open)
  434.             (display.Finished) ();
  435. }
  436.  
  437. void            ColourInit()
  438. {
  439.     Pixmap          icon;
  440.     XSizeHints      hints;
  441.     long            size, i;
  442.     XSetWindowAttributes attrib;
  443.  
  444.     if ((theDisplay = XOpenDisplay(display_name)) == NULL) {
  445.     fprintf(stderr, "Can't open X server %s.\n",
  446.         XDisplayName(display_name));
  447.     exit(1);
  448.     }
  449.     theScreen = DefaultScreen(theDisplay);
  450.  
  451.     /* screen dimensions */
  452.     disp_wide = DisplayWidth(theDisplay, theScreen);
  453.     disp_high = DisplayHeight(theDisplay, theScreen);
  454.  
  455.     theWindow = XCreateSimpleWindow(theDisplay, RootWindow(theDisplay, theScreen),
  456.                   (disp_wide - Frame.Screen_Width) / 2,
  457.                   (disp_high - Frame.Screen_Height) / 2,
  458.                   Frame.Screen_Width,
  459.                   Frame.Screen_Height, 2 /* border width */ ,
  460.               BlackPixel(theDisplay, theScreen), WhitePixel(theDisplay, theScreen));
  461.  
  462.     /* create a graphics context for drawing */
  463.     gcvalues.function = GXcopy;
  464.     theGC = XCreateGC(theDisplay, theWindow, GCFunction, &gcvalues);
  465.  
  466.     /* make a cute icon */
  467.     icon = XCreateBitmapFromData(theDisplay, theWindow, xpov_bits, xpov_width,
  468.                  xpov_height);
  469.  
  470.     /* give a few clues about ourself */
  471.     hints.flags = PPosition | PSize | PMinSize;
  472.     hints.x = (disp_wide - Frame.Screen_Width) / 2;
  473.     hints.y = (disp_high - Frame.Screen_Height) / 2;
  474.     hints.width = Frame.Screen_Width;
  475.     hints.height = Frame.Screen_Height;
  476.     hints.min_width = 32;
  477.     hints.min_height = 32;
  478.  
  479.     XSetStandardProperties(theDisplay, theWindow, "povray", "povray", icon, NULL, 0,
  480.                &hints);
  481.  
  482.     /* only want to know about expose events */
  483.     XSelectInput(theDisplay, theWindow, ExposureMask);
  484.     XMapWindow(theDisplay, theWindow);
  485.  
  486.     BuildColormap();
  487.  
  488.     size = Frame.Screen_Width * Frame.Screen_Height;
  489.     data = (char *) XtMalloc(size);
  490.     for (i = 0; i < size; i++)
  491.     data[i] = 0;
  492.     xi = XCreateImage(theDisplay, DefaultVisual(theDisplay, theScreen), 8, ZPixmap, 0, data,
  493.         Frame.Screen_Width, Frame.Screen_Height, 8, Frame.Screen_Width);
  494. };
  495.  
  496. void            ColourClose()
  497. {
  498.     sleep(10);
  499.     XDestroyImage(xi);
  500.     XtFree(data);
  501.     XDestroyWindow(theDisplay, theWindow);
  502.     XCloseDisplay(theDisplay);
  503. }
  504.  
  505.  /* static */ int dither(x, y, Red, Green, Blue)
  506. register unsigned int x, y;
  507. unsigned char   Red, Green, Blue;
  508. {
  509.     /*
  510.      * Perform ordered dithering for halftone screen. For details, see
  511.      * Graphics Gems, Ed. Andrew Glassner, p. 176-178 Floyd-Steinberg dither
  512.      * would look better, but we would need more saved state, making the
  513.      * coding a lot uglier.  Since this is just a display hack and not an
  514.      * image processing package, I don't bother.
  515.      */
  516.     static unsigned int dm[] = {
  517.     0, 192, 48, 240, 12, 204, 60, 252,
  518.     128, 64, 176, 112, 140, 76, 188, 124,
  519.     32, 224, 16, 208, 44, 236, 28, 220,
  520.     160, 96, 144, 80, 172, 108, 156, 92,
  521.     8, 200, 56, 248, 4, 196, 52, 244,
  522.     136, 72, 184, 120, 132, 68, 180, 116,
  523.     40, 232, 24, 216, 36, 228, 20, 212,
  524.     168, 104, 152, 88, 164, 100, 148, 84
  525.     };
  526.     register unsigned long luminence =
  527.     (307 * Red + 599 * Green + 118 * Blue) / 1024;
  528.     return (luminence < dm[(x & 7) + ((y & 7) << 3)]);
  529. }
  530.  
  531. void            ColourPlot(x, y, Red, Green, Blue)
  532. int             x, y;
  533. unsigned char   Red, Green, Blue;
  534. {
  535.     long            thePixel;
  536.     int             r, g, b;
  537.     XEvent          report;
  538.     int             luminence;
  539.  
  540.     /* scale rgb to be in our 216 color space */
  541.     r = (Red * 216) / (256 * 36);
  542.     g = (Green * 216) / (256 * 36);
  543.     b = (Blue * 216) / (256 * 36);
  544.  
  545.     /* find the pixel we got */
  546.     thePixel = colorpixels[(r * 36) + (g * 6) + b];
  547.     XPutPixel(xi, x, y, thePixel);
  548.     /* on each pixel, copy a scanline.  Inefficient, but so what?  See above. */
  549.     XPutImage(theDisplay, theWindow, theGC, xi, 0, y, 0, y, Frame.Screen_Width, 1);
  550.  
  551.     /* poll for exposure events */
  552.     if (XCheckIfEvent(theDisplay, &report, evtPred, "blah")) {
  553.     XPutImage(theDisplay, theWindow, theGC, xi, 0, 0, 0, 0, Frame.Screen_Width, y + 1);
  554.     }
  555. }
  556.  
  557. void unix_init_POVRAY PARAMS((void))
  558. {
  559. }
  560.  
  561. int             matherr(x)
  562. struct exception *x;
  563. {
  564.     switch (x->type) {
  565.       case DOMAIN:
  566.       case OVERFLOW:
  567.     x->retval = 1.0e17;
  568.     break;
  569.  
  570.       case SING:
  571.       case UNDERFLOW:
  572.     x->retval = 0.0;
  573.     break;
  574.  
  575.       default:
  576.     break;
  577.     }
  578.     return (1);
  579. }
  580.  
  581. extern void     BWInit(), BWClose(), BWFinished(), BWPlot();
  582.  
  583. void            display_init()
  584. {
  585.     Pixmap          icon;
  586.     XSizeHints      hints;
  587.     long            size, i;
  588.     XSetWindowAttributes attrib;
  589.  
  590.     if ((theDisplay = XOpenDisplay(display_name)) == NULL) {
  591.     fprintf(stderr, "Can't open X server %s.\n",
  592.         XDisplayName(display_name));
  593.     exit(1);
  594.     }
  595.     
  596.     screen_open = 1;
  597.     
  598.     theScreen = DefaultScreen(theDisplay);
  599.     iscolor = (XDisplayCells(theDisplay, theScreen) > 2);
  600.  
  601.     if (iscolor) {
  602.     display.Init = ColourInit;
  603.     display.Close = ColourClose;
  604.     display.Finished = ColourFinished;
  605.     display.Plot = ColourPlot;
  606.     }
  607.     else {
  608.     display.Init = BWInit;
  609.     display.Close = BWClose;
  610.     display.Finished = BWFinished;
  611.     display.Plot = BWPlot;
  612.     }
  613.  
  614.     XCloseDisplay(theDisplay);
  615.     (display.Init) ();
  616.  
  617. }
  618.